//<SCRIPT>
/*
Helper class for dealing with enumerated configuration file lists like the 
following:
<List Name="HTTPDeliverable">
    <Var Path_0="/admin"/>
    <Var Path_2="/ramgen"/>
    <Var Path_1="/farm"/>
    <Var Path_3="/scalable"/>
</List>
Usage:
in server code do something like this:
emitPropsToJSArray( "config.HTTPDeliverable", "httpDelivList", 0, 0 );
On the client side, instantiate an EnumPropList object like so:
var httpEnumList = new EnumPropList( httpDelivList, "config.HTTPDeliverable", "Path_" );
during the onLoad handler for your page, use this to populate a <SELECT> list:
httpEnumList.fillSelectList( theForm.HTTPLIST );
uses a form control to display current values and retrieve new values,
when a select control is used the class addes the 
*/
function EnumPropList ( name, initVals, listEnumPrefix, enumIncAmount, ctrlName )
{

	this.base = PropList ;
	this.base( name );
	this.m_oForm = null;
	this.m_ctrlName = ( ctrlName ? ctrlName : name );
	this.m_origValues = new Array();
	this.m_prefix = ( (listEnumPrefix!=null) ? listEnumPrefix : "item_" );
	if ( (enumIncAmount == null) || 
		 (parseInt( enumIncAmount ) != enumIncAmount) )
	{
		this.m_enumIncAmount = 1;
	}
	else
	{
		this.m_enumIncAmount = enumIncAmount;
	}
	this.m_newValues = new Array();
	this.m_propSet = 1;
	if ( initVals )
	{
		this.initProps( initVals );
	}
	return this ;
}
EnumPropList.prototype = new PropList ;
EnumPropList.prototype.copy = function ( destList )
{

	destList.m_parent = this.m_parent ;
	destList.m_oldName = "" ;
	destList.m_status = "added" ;
	destList.m_bRestart = this.m_bRestart ;
	destList.m_bRestartOnDelete = this.m_bRestartOnDelete ;
	// make copys of the this list's original values
	destList.m_origValues = copyIndexedArray( this.m_origValues );
	destList.m_newValues = copyIndexedArray( this.m_newValues );
	destList.m_oForm = this.m_oForm;
}	// copy ()
EnumPropList.prototype.initProps = function ( initVals )
{
	this.m_origValues.length = 0;
	// pivot the original list into a hash for easy lookup (eliminates duplicates also)
	if ( initVals )
	{

		var sortList = new Array();
		for ( var key in initVals )
		{
			// does key match the form listEnumPrefix<Enum>?
			if ( -1 != this.parseEnumIndex( key ) )
			{
				sortList[ sortList.length ] = key;
			}
		}
		if ( isIE )
			sortList.sort( sortCaseInsensitive );
		else
			sortList.sort();	
		for ( var i = 0; i < sortList.length; i++ )
		{
			var key = sortList[ i ];
			var keyValue = initVals[ key ];
			this.m_origValues[ this.m_origValues.length ] = keyValue ;
			this.m_newValues[ this.m_newValues.length ] = keyValue ;

		}
	}
}	// initProps
EnumPropList.prototype.createNew = function ( newName )
{

	return null ;	
}	// copy ()
EnumPropList.prototype.setForm = function ( oForm )
{
	if ( oForm )
		this.m_oForm = oForm;
}
// save the contents of selCtrl into m_newValues
EnumPropList.prototype.validate = function ( oForm, fIgnoreErrors )
{

	return true;
}	// validate ()
// convert the contents of the associated Select control into
// a param string
EnumPropList.prototype.buildParamString = function ( rootPropPath, fForce, paramCallbackFunc )
{
	if ( (!fForce) && 
		 (this.m_newValues.toString() == this.m_origValues.toString()) )
		return "";
	// first destroy the old list
	var posLastDotFromEnd = 0;
	if ( "." == rootPropPath.charAt( rootPropPath.length - 1 ) )
		posLastDotFromEnd = -1 ;
	var qStr = buildParam( rootPropPath.slice( 0, posLastDotFromEnd ), "" );
	if ( paramCallbackFunc )
	{
		qStr = paramCallbackFunc( this, null, qStr );
	}
	// recreate it using the contents of m_newValues
	var enumIndex = this.m_enumIncAmount;
	// make copys of the this list's original values
	for ( var i = 0; i < this.m_newValues.length; i++ )
	{
		var propValue = this.m_newValues[ i ];
		if ( ! isBlank( propValue ) )
		{
			paramStr = buildParam( rootPropPath + this.m_prefix + enumIndex, propValue );
			if ( paramCallbackFunc )
			{
				paramStr = paramCallbackFunc( this, null, paramStr );
			}
			qStr += paramStr ;
			enumIndex += this.m_enumIncAmount;
		}
	}
	return qStr ;
}	// buildParamString ()
EnumPropList.prototype.reset = function ()
{

	this.m_newValues = copyIndexedArray( this.m_origValues );
}	// reset ()
EnumPropList.prototype.propCount = function ()
{
	var nCount = this.m_newValues.length ;

	return nCount ;
}	// nCount ()
EnumPropList.prototype.clearList = function ()
{
	this.m_newValues.length = 0;
}
EnumPropList.prototype.isDirty = function ( oForm )
{

	return ( this.m_newValues.toString() != this.m_origValues.toString() );
}	// isDirty ()
EnumPropList.prototype.commit = function ()
{

	this.m_origValues = copyIndexedArray( this.m_newValues );
}	// commit ()
EnumPropList.prototype.parseEnumIndex = function ( enumName )
{
	var enumIndex = -1 ;
	var regExp = new RegExp( "^" + escRegExMetaChars( this.m_prefix ) + "(\\d+)" + "$", "i" );
	// make sure enumName is a string
	enumName = enumName + "";
	// does key match the form listEnumPrefix<Enum>?
	var tempA = enumName.match( regExp );
	if ( tempA && tempA[ 1 ] )
	{
		enumIndex = parseInt( tempA[ 1 ] );
		if ( isNaN( enumIndex ) )
			enumIndex = -1 ;
	}
	return enumIndex;
}	
EnumPropList.prototype.propNames = function ()
{
	return null;
}
EnumPropList.prototype.addPropValue = function ( oForm, propValue )
{

}	// addPropValue ()
EnumPropList.prototype.fillForm = function ( oForm )
{

}	// PropList.prototype.fillForm ()
EnumPropList.prototype.getDisplayCtrl = function ( oForm )
{
	if ( oForm ) this.setForm( oForm );

	if ( this.m_oForm )
	{
		return this.m_oForm[ this.m_ctrlName ];
	}
	return null ;
}	// PropList.prototype.getDisplayCtrl ()
// overrides of PropList methods that 'do nothing'
EnumPropList.prototype.initSubLists = function ( initVals, propSet ){}
EnumPropList.prototype.value = function ( name ){return null;}
EnumPropList.prototype.addSubList = function ( subList, status ){}
EnumPropList.prototype.copySubList = function ( srcName, copyName ){}
EnumPropList.prototype.clearForm = function ( form ){}
EnumPropList.prototype.fillSelectList2 = function ( selectCtrl, propName ){}
EnumPropList.prototype.checkDescriptionUniqueness = function ( extList, ctrlDescription ){}
EnumPropList.prototype.checkListNameUniqueness = function ( extList, listName ){}
EnumPropList.prototype.checkMounPointUniqueness = function ( extList, description, mountPoint, ctrl /*optional*/ ){}
EnumPropList.prototype.propSearch = function ( propNameExp, callback ){}
EnumPropList.prototype.save = function ( form ){}
EnumPropList.prototype.setFormDefaults = function ( form ){}
EnumPropList.prototype.resetToDefaults = function ( form ){}
/****
	EnumPropListSel
	EnumPropListSel sub classes EnumPropListSel and uses a Select Control to display items
****/
function EnumPropListSel ( name, initVals, listEnumPrefix, enumIncAmount, ctrlName )
{

	this.base = EnumPropList ;
	this.base( name, initVals, listEnumPrefix, enumIncAmount, ctrlName );
	return this ;
}
EnumPropListSel.prototype = new EnumPropList ;
EnumPropListSel.prototype.createNew = function ( newName, fCopy )
{
	if ( isBlank( newName ) ) 
		newName = this.m_name ; 

	var newList = new EnumPropListSel( newName, null, this.m_prefix, this.m_enumIncAmount, this.m_ctrlName );
	if ( fCopy )
		this.copy( newList );
	return newList;
}	// createNew
EnumPropListSel.prototype.swapValueOrder = function ( oForm, dir )
{

	if ( oForm ) this.setForm( oForm );

	selectMoveItem( this.getDisplayCtrl(), dir );
}	// swapValueOrder ()
EnumPropListSel.prototype.addPropValue = function ( oForm, propValue )
{

	if ( oForm ) this.setForm( oForm );

	var ctrl = this.getDisplayCtrl();
	if ( ctrl )
	{
		// make sure this propValue isn't in the list already
		if ( -1 == selectFind( ctrl, propValue ) )
		{
			selAddOption( ctrl, propValue );
		}
	}
}	// addPropValue ()
EnumPropListSel.prototype.removeCurSelValue = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );

	selectDel( this.getDisplayCtrl() );
	return true ;
}	// removeProp ()
// save the contents of selCtrl into m_newValues
EnumPropListSel.prototype.validate = function ( oForm, fIgnoreErrors )
{

	if ( oForm ) this.setForm( oForm );

	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return null ;
	// first destroy the current list
	this.m_newValues = new Array();
	for ( var i= 0; i < ctrl.options.length; i++ )
	{
		var propValue = ctrl.options[ i ].value ;
		if ( ! isBlank( propValue ) )
		{
			this.m_newValues[ this.m_newValues.length ] = propValue ;
		}
	}
	return null ;
}	// validate ()
EnumPropListSel.prototype.fillForm = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );

	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return ;
	ctrl.options.length = 0;
	for ( var i = 0; i < this.m_newValues.length; i++ )
	{
		selAddOption( ctrl, this.m_newValues[ i ] );
	}
}	// fillForm ()
EnumPropListSel.prototype.isFormDirty = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );
	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return false ;
	var tempA = new Array();
	for ( var i= 0; i < ctrl.options.length; i++ )
	{
		var propValue = ctrl.options[ i ].value ;
		if ( ! isBlank( propValue ) )
		{
			tempA[ tempA.length ] = propValue;
		}
	}
	return (tempA.toString() != this.m_origValues.toString());
}	// isFormDirty ()
/****
	EnumPropListText
	EnumPropListText sub classes EnumPropList and uses an edit or textarea Control to display items
****/
function EnumPropListText ( name, initVals, listEnumPrefix, enumIncAmount, ctrlName, sepStr, parseRegExp )
{

	this.base = EnumPropList ;
	this.base( name, initVals, listEnumPrefix, enumIncAmount, ctrlName );
	// sepStr is used to seperate the property values when displaying them
	// in a text control. Ex: ", "
	this.m_sepStr = sepStr;
	// parseRegExp is used when parsing out the property values from a text control
	// Ex: "\s*,\s*"
	this.m_parseRegExp = (parseRegExp ? parseRegExp : new RegExp( sepStr ) );
	return this ;
}
EnumPropListText.prototype = new EnumPropList ;
EnumPropListText.prototype.createNew = function ( newName, fCopy )
{
	if ( isBlank( newName ) ) 
		newName = this.m_name ; 

	var newList = new EnumPropListText( newName, null, this.m_prefix, 
		this.m_enumIncAmount, this.m_ctrlName, this.m_sepStr, this.m_parseRegExp );
	if ( fCopy )
		this.copy( newList );
	return newList;
}	// createNew
EnumPropListText.prototype.getValuesHash = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );
	var valuesHash = new Object();
	var ctrl = this.getDisplayCtrl();
	if ( ctrl )
	{
		var sPropValues = getCtrlValue( ctrl );
		var tempA = sPropValues.split( this.m_parseRegExp );
		for ( var i= 0; i < tempA.length; i++ )
		{
			if ( (!isBlank( tempA[ i ] )) && 
				   isBlank( valuesHash[ tempA[ i ] ] ) )
			{
				valuesHash[ tempA[ i ] ] = 0;
			}
		}
	}
	return valuesHash ;
}	// getValuesHash ()
EnumPropListText.prototype.getValuesArray = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );
	var valuesArray = new Array();
	var valuesHash = this.getValuesHash();
	var ctrl = this.getDisplayCtrl();
	if ( ctrl )
	{
		var sPropValues = getCtrlValue( ctrl );
		var tempA = sPropValues.split( this.m_parseRegExp );
		var nextX = 0;
		for ( var i= 0; i < tempA.length; i++ )
		{
			if ( (!isBlank( tempA[ i ] )) && 
				 (0 == valuesHash[ tempA[ i ] ]) )
			{
				valuesArray[ nextX++ ] = tempA[ i ];
				valuesHash[ tempA[ i ] ] = 1;
			}
		}
	}
	return valuesArray ;
}	// getValuesArray ()
EnumPropListText.prototype.fillForm = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );

	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return ;
	var sPropValues = "";
	for ( var i = 0; i < this.m_newValues.length; i++ )
	{
		sPropValues += this.m_newValues[ i ];
		if ( i < (this.m_newValues.length - 1) )
		{
			sPropValues += this.m_sepStr ;
		}
	}
	setCtrlValue( ctrl, sPropValues, true );
}	// fillForm ()
EnumPropListText.prototype.addPropValue = function ( oForm, propValue )
{

	if ( oForm ) this.setForm( oForm );

	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return;
	// make sure this propValue isn't in the text ctrl already
	if ( isBlank( this.getValuesHash()[ propValue ] ) )
	{
		var sPropValues = getCtrlValue( ctrl );
		sPropValues += (isBlank(sPropValues) ? "" : this.m_sepStr) + propValue ;
		setCtrlValue( ctrl, sPropValues );
	}
}	// addPropValue ()
EnumPropListText.prototype.isFormDirty = function ( oForm )
{

	if ( oForm ) this.setForm( oForm );
	var ctrl = this.getDisplayCtrl();
	if ( ! ctrl ) return false;

	return (this.getValuesArray().toString() != this.m_origValues.toString());
}	// isFormDirty ()
// save the contents of the text ctrl into m_newValues
EnumPropListText.prototype.validate = function ( oForm, fIgnoreErrors )
{

	if ( oForm ) this.setForm( oForm );
	this.m_newValues = this.getValuesArray();
	return true ;
}	// validate ()
//</SCRIPT>

